﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
using YArchitech.ProgressBar;
using YJKRevitBase.WinForm;
using YJKOpeningCommon.DbOpening;
using YJKOpeningCommon.OpeningProfile;
using YJKOpeningCommon.Public;
using YJKOpeningDesignInput.Public;

namespace YJKOpeningDesignInput.DbOpeningCreatorFactory
{
	internal class DbFloorOpeningCreatorFactory : DbOpeningBaseCreatorFactory
	{
        public DbFloorOpeningCreatorFactory(ref List<Document> lstDoc, WindowHandle handle, Dictionary<string, int> dicOpenProfileData)
            : base(ref lstDoc, handle, dicOpenProfileData)
		{
		}

		public override bool CreateDbOpening(MEPData mepData, ref LinkedList<DbOpeningBase> lstDbOpening)
		{
			return this.GetOpeningDataByDuct(mepData.m_lstDuct, mepData.m_lstInfos, ref lstDbOpening) && this.GetOpeningDataByCableTray(mepData.m_lstCableTray, mepData.m_lstInfos, ref lstDbOpening) && this.GetOpeningDataByPipe(mepData.m_lstPipe, mepData.m_lstInfos, ref lstDbOpening);
		}

		private bool GetOpeningDataByDuct(List<Duct> lstDuct, List<YJKOpeningDesignInput.Public.PointSort> lstInfos, ref LinkedList<DbOpeningBase> lstDbopening)
		{
			ProgressBarForm progressBarForm = new ProgressBarForm(lstDuct.Count, ProgressBarStyle.Blocks, true);
			bool result;
			try
			{
				progressBarForm.Text = "风管和板碰撞检测";
				progressBarForm.ShowInTaskbar = false;
				progressBarForm.Show(this.m_hWndRevit);
				List<Floor> list = new List<Floor>();
				foreach (Duct duct in lstDuct)
				{
					foreach (Autodesk.Revit.DB.Document doc in this.m_lstDoc)
					{
						list.AddRange(Interface.GetAllIntersectSubject<Floor>(duct, doc, BuiltInCategory.OST_Floors));
					}
					if (list.Count == 0)
					{
						progressBarForm.RefreshProgressBar();
					}
					else
					{
						if (!this.TraveAllFloor(list, duct, lstInfos, ref lstDbopening))
						{
							progressBarForm.Dispose();
							return false;
						}
						list.Clear();
						progressBarForm.RefreshProgressBar();
						if (progressBarForm.m_stopTag)
						{
							return false;
						}
					}
				}
				progressBarForm.Dispose();
				result = true;
			}
			catch (Exception ex)
			{
				progressBarForm.Dispose();
				ExceptionLog.WriteLog(ex.Message, true);
				result = false;
			}
			return result;
		}

		private bool GetOpeningDataByCableTray(List<CableTray> lstCableTary, List<YJKOpeningDesignInput.Public.PointSort> lstInfos, ref LinkedList<DbOpeningBase> lstDbopening)
		{
			ProgressBarForm progressBarForm = new ProgressBarForm(lstCableTary.Count, ProgressBarStyle.Blocks, true);
			bool result;
			try
			{
				progressBarForm.Text = "电缆桥架和板碰撞检测";
				progressBarForm.ShowInTaskbar = false;
				progressBarForm.Show(this.m_hWndRevit);
				List<Floor> list = new List<Floor>();
				foreach (CableTray cableTray in lstCableTary)
				{
					foreach (Autodesk.Revit.DB.Document doc in this.m_lstDoc)
					{
						list.AddRange(Interface.GetAllIntersectSubject<Floor>(cableTray, doc, BuiltInCategory.OST_Floors));
					}
					if (list.Count == 0)
					{
						progressBarForm.RefreshProgressBar();
					}
					else
					{
						if (!this.TraveAllFloor(list, cableTray, lstInfos, ref lstDbopening))
						{
							progressBarForm.Dispose();
							return false;
						}
						list.Clear();
						progressBarForm.RefreshProgressBar();
						if (progressBarForm.m_stopTag)
						{
							return false;
						}
					}
				}
				progressBarForm.Dispose();
				result = true;
			}
			catch (Exception)
			{
				progressBarForm.Dispose();
				result = false;
			}
			return result;
		}

		private bool GetOpeningDataByPipe(List<Pipe> lstPipe, List<YJKOpeningDesignInput.Public.PointSort> lstInfos, ref LinkedList<DbOpeningBase> lstDbopening)
		{
			ProgressBarForm progressBarForm = new ProgressBarForm(lstPipe.Count, ProgressBarStyle.Blocks, true);
			bool result;
			try
			{
				progressBarForm.Text = "水管和板碰撞检测";
				progressBarForm.ShowInTaskbar = false;
				progressBarForm.Show(this.m_hWndRevit);
				List<Floor> list = new List<Floor>();
				foreach (Pipe pipe in lstPipe)
				{
					foreach (Autodesk.Revit.DB.Document doc in this.m_lstDoc)
					{
						list.AddRange(Interface.GetAllIntersectSubject<Floor>(pipe, doc, BuiltInCategory.OST_Floors));
					}
					if (list.Count == 0)
					{
						progressBarForm.RefreshProgressBar();
					}
					else
					{
						if (!this.TraveAllFloor(list, pipe, lstInfos, ref lstDbopening))
						{
							progressBarForm.Dispose();
							return false;
						}
						list.Clear();
						progressBarForm.RefreshProgressBar();
						if (progressBarForm.m_stopTag)
						{
							return false;
						}
					}
				}
				progressBarForm.Dispose();
				result = true;
			}
			catch (Exception)
			{
				progressBarForm.Dispose();
				result = false;
			}
			return result;
		}

		private bool TraveAllFloor(List<Floor> lstFloor, Element mepCurveElem, List<YJKOpeningDesignInput.Public.PointSort> lstInfos, ref LinkedList<DbOpeningBase> lstDbOpening)
		{
			try
			{
				Line mepcurveLine = Interface.GetMEPCurveLine(mepCurveElem);
				if (mepcurveLine == null)
				{
					return false;
				}
				foreach (Floor floor in lstFloor)
				{
					List<XYZ> cvIntersect2FloorPoints = CommonInterface.GetCvIntersect2FloorPoints(mepcurveLine, floor);
					if (cvIntersect2FloorPoints != null)
					{
						foreach (XYZ xyz in cvIntersect2FloorPoints)
						{
							if (xyz != null)
							{
								OpeningData openingData = new OpeningData();
								DbOpeningBase value = null;
								OpeningProfileBase openingProfileBase = null;
								if (mepCurveElem is Duct)
								{
									if ((mepCurveElem as Duct).get_Parameter(BuiltInParameter.ELEM_FAMILY_PARAM).AsValueString() != "圆形风管")
									{
										value = new DbRectFloorOpening();
										if (!Interface.GetOpeningDatas(ref value, ref openingData, xyz, floor, mepCurveElem, lstInfos))
										{
											continue;
										}
										openingProfileBase = new OpeningProfileRect();
										OpeningProfileRect openingProfileRect = openingProfileBase as OpeningProfileRect;
										openingProfileRect.m_cutHeight = openingData.m_cutHeight;
										openingProfileRect.m_cutWidth = openingData.m_cutWidth;
										openingProfileRect.m_angle = openingData.m_cutAngle;
										openingData.m_extendDist = AssistFunc.mmToFeet(Convert.ToDouble(this.m_dicOpeningProfileData["RectOpeningOutSize"]));
									}
									else
									{
										value = new DbCircleFloorOpening();
										if (!Interface.GetOpeningDatas(ref value, ref openingData, xyz, floor, mepCurveElem, lstInfos))
										{
											continue;
										}
										openingProfileBase = new OpeningProfileCircle();
										(openingProfileBase as OpeningProfileCircle).m_dCutDiameter = openingData.m_cutDia;
										openingData.m_extendDist = AssistFunc.mmToFeet(Convert.ToDouble(this.m_dicOpeningProfileData["CircleOpeningOutSize"]));
									}
								}
								else if (mepCurveElem is CableTray)
								{
									value = new DbRectFloorOpening();
									if (!Interface.GetOpeningDatas(ref value, ref openingData, xyz, floor, mepCurveElem, lstInfos))
									{
										continue;
									}
									openingProfileBase = new OpeningProfileRect();
									OpeningProfileRect openingProfileRect2 = openingProfileBase as OpeningProfileRect;
									openingProfileRect2.m_cutHeight = openingData.m_cutHeight;
									openingProfileRect2.m_cutWidth = openingData.m_cutWidth;
									openingProfileRect2.m_angle = openingData.m_cutAngle;
									openingData.m_extendDist = AssistFunc.mmToFeet(Convert.ToDouble(this.m_dicOpeningProfileData["RectOpeningOutSize"]));
								}
								else if (mepCurveElem is Pipe)
								{
									value = new DbCircleFloorOpening();
									if (!Interface.GetOpeningDatas(ref value, ref openingData, xyz, floor, mepCurveElem, lstInfos))
									{
										continue;
									}
									openingProfileBase = new OpeningProfileCircle();
									(openingProfileBase as OpeningProfileCircle).m_dCutDiameter = openingData.m_cutDia;
									openingData.m_extendDist = AssistFunc.mmToFeet(Convert.ToDouble(this.m_dicOpeningProfileData["CircleOpeningOutSize"]));
								}
								openingData.m_tolerance = AssistFunc.mmToFeet(Convert.ToDouble(this.m_dicOpeningProfileData["CompositeTolerance"]));
								Interface.SetOpeningProfile(ref openingProfileBase, openingData);
								Interface.SetOpeningData2Opening(openingData, ref value, openingProfileBase);
								lstDbOpening.AddLast(value);
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				ExceptionLog.WriteLog(ex.Message, true);
				return false;
			}
			return true;
		}
	}
}
